package com.shrct.businessprocess.purchase.impl;

import com.google.common.base.Objects;
import com.shrct.businessprocess.budget.RCBudget;
import com.shrct.businessprocess.budget.RCCost4ACTItem;
import com.shrct.businessprocess.budget.RCCostBreakDown;
import com.shrct.businessprocess.budget.impl.RCBudgetImpl;
import com.shrct.businessprocess.common.CurrencyType;
import com.shrct.businessprocess.money.Moneys;
import com.shrct.businessprocess.project.RCExchangeRate;
import com.shrct.businessprocess.project.RCProject;
import com.shrct.businessprocess.project.RCProjectMoney;
import com.shrct.businessprocess.project.RCRealMoney;
import com.shrct.businessprocess.purchase.RCPay;
import com.shrct.businessprocess.purchase.RCPayRequest;
import com.shrct.businessprocess.purchase.RCPayType;
import com.shrct.businessprocess.purchase.impl.RCPayImpl;
import com.shrct.businessprocess.purchase.proxy.RCPayRequestProxy;
import edu.fudan.mylang.pf.BaseModelObject;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import javax.persistence.AssociationOverride;
import javax.persistence.AssociationOverrides;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.eclipse.xtext.xbase.lib.CollectionLiterals;
import org.eclipse.xtext.xbase.lib.Functions.Function1;
import org.eclipse.xtext.xbase.lib.Functions.Function2;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.eclipse.xtext.xbase.lib.ObjectExtensions;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
import org.hibernate.annotations.DiscriminatorOptions;

@Entity
@DiscriminatorValue("RCPAYREQUEST_TYPE")
@DiscriminatorOptions(force = true)
@DiscriminatorColumn(length = 64)
@Table(name = "rcpayrequest")
public abstract class RCPayRequestImpl extends BaseModelObject implements RCPayRequest {
  public RCPayRequestImpl() {
    super();
  }
  
  @OneToMany(targetEntity = RCPayImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }, mappedBy = "payRequest")
  private Collection<RCPay> purchasePays = new java.util.ArrayList<com.shrct.businessprocess.purchase.RCPay>();;
  
  public Collection<RCPay> getPurchasePays() {
    return this.purchasePays;
  }
  
  public RCPay createAndAddtoPurchasePays(final RCBudget budget) {
    getPurchasePays().size();
    com.shrct.businessprocess.purchase.RCPay rCPay = new com.shrct.businessprocess.purchase.impl.RCPayImpl(budget,this);
    getObjectFactory().create(rCPay);
    getPurchasePays().add(rCPay);
    return rCPay;
    
  }
  
  public RCPay createAndAddtoPurchasePays(final RCBudget budget, final Procedure1<RCPay> updater) {
    getPurchasePays().size();
    com.shrct.businessprocess.purchase.RCPay rCPay = new com.shrct.businessprocess.purchase.impl.RCPayImpl(budget,this);
    getObjectFactory().create(rCPay);
    getPurchasePays().add(rCPay);
    return rCPay;
    
  }
  
  public RCPayRequest removeAllPurchasePays() {
    for(RCPay obj : this.purchasePays){
    	getObjectFactory().delete(obj);
    }
    this.purchasePays.clear();
    return this;	
    
  }
  
  public RCPayRequest removeFromPurchasePays(final RCPay rCPay) {
    this.purchasePays.remove(rCPay);
    getObjectFactory().delete(rCPay);
    return this;
    
  }
  
  private RCPayType payType;
  
  public RCPayType getPayType() {
    return this.payType;
  }
  
  public RCPayRequest setPayType(final RCPayType payType) {
    this.payType = payType;
    return this;			
    
  }
  
  private Date wishPayDate;
  
  public Date getWishPayDate() {
    return this.wishPayDate;
  }
  
  public RCPayRequest setWishPayDate(final Date wishPayDate) {
    this.wishPayDate = wishPayDate;
    return this;			
    
  }
  
  @Embedded
  @AttributeOverrides(value = { @AttributeOverride(name = "amount", column = @Column(name = "amount_amount") ), @AttributeOverride(name = "workaround", column = @Column(name = "amount_workaround") ) } )
  @AssociationOverrides(value = @AssociationOverride(name = "exchange", joinColumns = @JoinColumn(name = "amount_exchange") ) )
  private RCProjectMoney amount = com.shrct.businessprocess.project.RCProjectMoney.create();
  
  public RCProjectMoney getAmount() {
    return this.amount;
  }
  
  public RCPayRequest setAmount(final RCProjectMoney amount) {
    this.amount = amount;
    return this;			
    
  }
  
  private String comment;
  
  public String getComment() {
    return this.comment;
  }
  
  public RCPayRequest setComment(final String comment) {
    this.comment = comment;
    return this;			
    
  }
  
  private Boolean isFinished = Boolean.valueOf(false);
  
  public Boolean getIsFinished() {
    return this.isFinished;
  }
  
  public RCPayRequest setIsFinished(final Boolean isFinished) {
    this.isFinished = isFinished;
    return this;			
    
  }
  
  private Date finishDate;
  
  public Date getFinishDate() {
    return this.finishDate;
  }
  
  public RCPayRequest setFinishDate(final Date finishDate) {
    this.finishDate = finishDate;
    return this;			
    
  }
  
  private Date theStartDate;
  
  public Date getTheStartDate() {
    return this.theStartDate;
  }
  
  public RCPayRequest setTheStartDate(final Date theStartDate) {
    this.theStartDate = theStartDate;
    return this;			
    
  }
  
  @JoinColumn(name = "thebudget_id")
  @ManyToOne(targetEntity = RCBudgetImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RCBudget thebudget;
  
  public RCBudget getThebudget() {
    return this.thebudget;
  }
  
  public RCPayRequest setThebudget(final RCBudget thebudget) {
    this.thebudget = thebudget;
    return this;			
    
  }
  
  public Double getTaxRate() {
    return Double.valueOf(0d);
  }
  
  public RCProjectMoney getTotalPaidProjectAmount() {
    final Function1<RCPay,RCProjectMoney> _function = new Function1<RCPay,RCProjectMoney>() {
        public RCProjectMoney apply(final RCPay it) {
          RCProjectMoney _projectAmount = it.getProjectAmount();
          return _projectAmount;
        }
      };
    Iterable<RCProjectMoney> _map = IterableExtensions.<RCPay, RCProjectMoney>map(this.purchasePays, _function);
    RCExchangeRate _defaultExchangeRate = this.getDefaultExchangeRate();
    RCProjectMoney _sum = Moneys.sum(_map, _defaultExchangeRate);
    return _sum;
  }
  
  public RCProjectMoney getRemainProjectAmount() {
    RCProjectMoney _totalPaidProjectAmount = this.getTotalPaidProjectAmount();
    RCProjectMoney _substract = this.amount.substract(_totalPaidProjectAmount);
    return _substract;
  }
  
  public RCRealMoney getTotalPaidAmount() {
    RCRealMoney _xblockexpression = null;
    {
      RCBudget _budget = this.getBudget();
      RCCostBreakDown _cbd = _budget.getCbd();
      RCProject _project = _cbd.getProject();
      final CurrencyType hostCurrencyType = _project.getCurrencyType();
      final RCExchangeRate de = this.getDefaultExchangeRate();
      final Function1<RCPay,RCRealMoney> _function = new Function1<RCPay,RCRealMoney>() {
          public RCRealMoney apply(final RCPay it) {
            RCRealMoney _amount = it.getAmount();
            return _amount;
          }
        };
      Iterable<RCRealMoney> _map = IterableExtensions.<RCPay, RCRealMoney>map(this.purchasePays, _function);
      final Function2<RCRealMoney,RCRealMoney,RCRealMoney> _function_1 = new Function2<RCRealMoney,RCRealMoney,RCRealMoney>() {
          public RCRealMoney apply(final RCRealMoney m1, final RCRealMoney m2) {
            RCRealMoney _plus = m1.plus(m2, hostCurrencyType);
            return _plus;
          }
        };
      RCRealMoney result = IterableExtensions.<RCRealMoney>reduce(_map, _function_1);
      RCRealMoney _xifexpression = null;
      boolean _equals = Objects.equal(result, null);
      if (_equals) {
        RCRealMoney _rCRealMoney = new RCRealMoney();
        final Procedure1<RCRealMoney> _function_2 = new Procedure1<RCRealMoney>() {
            public void apply(final RCRealMoney it) {
              it.setAmount(Double.valueOf(0d));
              CurrencyType _currencyType = de.getCurrencyType();
              it.setCurrencyType(_currencyType);
              Double _rate = de.getRate();
              it.setExchangeRate(_rate);
            }
          };
        RCRealMoney _doubleArrow = ObjectExtensions.<RCRealMoney>operator_doubleArrow(_rCRealMoney, _function_2);
        _xifexpression = _doubleArrow;
      } else {
        _xifexpression = result;
      }
      _xblockexpression = (_xifexpression);
    }
    return _xblockexpression;
  }
  
  public Iterable<RCCost4ACTItem> getCost4ACItems() {
    RCCost4ACTItem _rCCost4ACTItem = new RCCost4ACTItem();
    final Procedure1<RCCost4ACTItem> _function = new Procedure1<RCCost4ACTItem>() {
        public void apply(final RCCost4ACTItem it) {
          RCBudget _budget = RCPayRequestImpl.this.getBudget();
          it.setBudget(_budget);
          String _entityName = RCPayRequestImpl.this.getEntityName();
          it.setTitle(_entityName);
          Double _hostAmount = RCPayRequestImpl.this.amount.toHostAmount();
          it.setAmount(_hostAmount);
          Double _taxRate = RCPayRequestImpl.this.getTaxRate();
          it.setTaxRate(_taxRate);
          it.setDate(RCPayRequestImpl.this.finishDate);
        }
      };
    RCCost4ACTItem _doubleArrow = ObjectExtensions.<RCCost4ACTItem>operator_doubleArrow(_rCCost4ACTItem, _function);
    ArrayList<RCCost4ACTItem> _newArrayList = CollectionLiterals.<RCCost4ACTItem>newArrayList(_doubleArrow);
    return _newArrayList;
  }
  
  public RCPayRequestProxy toProxy() {
    com.shrct.businessprocess.purchase.proxy.RCPayRequestProxy proxy = new com.shrct.businessprocess.purchase.proxy.RCPayRequestProxy();
    proxy.setId(this.getId());
    if(this instanceof edu.fudan.mylang.pf.INamedModelObject){
    	proxy.setName(((edu.fudan.mylang.pf.INamedModelObject)this).getEntityName());
    }
    return proxy;
    
  }
}
